package com.tmt.im.common.service;

import com.alibaba.fastjson2.JSONObject;
import com.tmt.im.common.pojo.YunXinEventPoJo;
import com.tmt.im.common.yunxin.annotions._YunXinEvent;
import com.tmt.springboot.common.helper.IdSnowFlake;
import lombok.extern.slf4j.Slf4j;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.lang.IgniteBiPredicate;
import org.apache.ignite.resources.IgniteInstanceResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.Serial;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.time.OffsetDateTime;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Description TODO
 * @Author wuyi
 * @Date 2024/9/14 14:00
 * @Version 1.0
 **/
@Service
@Slf4j
public class YunXinEventService implements IgniteBiPredicate<UUID, JSONObject> {
    @Serial
    private static final long serialVersionUID = -4465325121566033193L;

    private final static Map<_YunXinEvent, Method> HandleMethodMap = new LinkedHashMap<>();

    private IgniteCache<Long, YunXinEventPoJo> eventCache;

    @IgniteInstanceResource
    private Ignite ignite;

    public YunXinEventService( ) {
        Method[] handleMethods = this.getClass().getDeclaredMethods();
        for (Method handleMethod : handleMethods) {
            _YunXinEvent ann = handleMethod.getAnnotation(_YunXinEvent.class);
            if (ann != null) {
                HandleMethodMap.put(ann, handleMethod);
            }
        }
    }

    @Override
    public boolean apply(UUID uuid, JSONObject jsonObject) {
        if (eventCache == null) {
            eventCache = ignite.cache(YunXinEventPoJo.CACHE_NAME);
        }
        processYunXinEventNotify(jsonObject);
        return true;
    }

    /**
     * 处理申请入群通知
     */
    @_YunXinEvent(eventType = "1", msgTypes = "TEAM_APPLY")
    public void processEvent_TEAM_APPLY(JSONObject event) {
        System.out.println("-----接收到入群申请通知-----");
        save(event);
    }

    /**
     * 处理拒绝入群申请通知
     */
    @_YunXinEvent(eventType = "1", msgTypes = "TEAM_APPLY_REJECT")
    public void processEvent_TEAM_APPLY_REJECT(JSONObject event) {
        System.out.println("-----接收到拒绝入群申请通知-----");
        save(event);
    }

    /**
     * 处理邀请进群通知
     */
    @_YunXinEvent(eventType = "1", msgTypes = "TEAM_INVITE")
    public void processEvent_TEAM_INVITE(JSONObject event) {
        System.out.println("-----接收到邀请进群通知-----");
        save(event);
    }

    /**
     * 处理拒绝邀请进群通知
     */
    @_YunXinEvent(eventType = "1", msgTypes = "TEAM_INVITE_REJECT")
    public void processEvent_TEAM_INVITE_REJECT(JSONObject event) {
        System.out.println("-----接收到拒绝邀请进群通知-----");
        save(event);
    }

    public void processEvent_OTHER(JSONObject event) {
        System.out.println("-----接收到不关注的通知-----");
        save(event);
    }

    private void save(JSONObject event) {
        YunXinEventPoJo yunXinEvent = YunXinEventPoJo.builder()
                .id(IdSnowFlake.getId())
                .content(event.toJSONString())
                .handled(false)
                .handleError(null)
                .version(0L)
                .createTime(new Timestamp(System.currentTimeMillis()))
                .insert(true)
                .build();
        eventCache.put(yunXinEvent.getKey(), yunXinEvent);
    }

    private void processYunXinEventNotify(JSONObject event) {
        String eventType = event.getString("eventType");
        String convType = event.getString("convType");
        String msgType = event.getString("msgType");
        try {
            Method method = HandleMethodMap.entrySet().stream().filter(x -> {
                _YunXinEvent ann = x.getKey();
                if (ann != null) {
                    return eventType.equals(ann.eventType())
                            && (!StringUtils.hasText(ann.convType().trim())
                            || "*".equals(ann.convType().trim())
                            || convType.equals(ann.convType()))
                            && Arrays.asList(ann.msgTypes()).contains(msgType);
                }
                return false;
            }).findFirst().map(Map.Entry::getValue).orElse(null);

            if (method != null) {
                method.invoke(this, event);
            } else {
                //兜底的处理方法。
                processEvent_OTHER(event);
            }
        } catch (Exception ex) {
            log.error("处理云信事件通知(eventType={}, covType={}, msgType={})出现异常：{}", eventType, convType, msgType, ex.getMessage());
        }
    }

}
